#include "leptjson.h"
#include <assert.h>  /* assert() */
#include <errno.h>   /* errno, ERANGE */
#include <math.h>    /* HUGE_VAL */
#include <stdlib.h>  /* NULL, malloc(), realloc(), free(), strtod() */
#include <string.h>  /* memcpy() */

#ifndef LEPT_PARSE_STACK_INIT_SIZE
#define LEPT_PARSE_STACK_INIT_SIZE 256
#endif

#define EXPECT(c, ch)       do { assert(*c->json == (ch)); c->json++; } while(0)
#define ISDIGIT(ch)         ((ch) >= '0' && (ch) <= '9')
#define ISDIGIT1TO9(ch)     ((ch) >= '1' && (ch) <= '9')
#define PUTC(c, ch)         do { *(char*)lept_context_push(c, sizeof(char)) = (ch); } while(0)/*将lept_context_push函数返回的指针									类型指定为 char * 并将该指针指向的值确定为 ch ，即单个单个字符地往stack数组中压入*/

typedef struct {
    const char* json;
    char* stack;/*存放字符数组的堆栈区，当然只是实现意义上的堆栈，而不是数据结构意义上的堆栈，本质上还是一个数组指针，指针名叫stack*/
    size_t size, top;/*size是当前堆栈的容量，即stack的总长度，top是栈顶的位置，即最后一个非空元素在stack中的索引值*/
}lept_context;/*存放临时数据*/

static void* lept_context_push(lept_context* c, size_t size) {/*根据压入的字符串的长度，在stack中分配不同的空间并返回相应的指针，实际上在此函数中，还未将字符的具体数据填入，仅仅是分配了下空间，本段代码中，都是将size大小设置为sizeof(char),意味着是以一个字符为单位进行插入*/
    void* ret;/*未定义类型的指针*/
    assert(size > 0);
    if (c->top + size >= c->size) {/*空间不足，重新分配空间*/
        if (c->size == 0)/*还未分配空间*/
            c->size = LEPT_PARSE_STACK_INIT_SIZE;
        while (c->top + size >= c->size)
            c->size += c->size >> 1;  /* c->size x 1.5  >>是二进制右移运算符，将数字变成原来的一半*/
        c->stack = (char*)realloc(c->stack, c->size);
    }
    ret = c->stack + c->top;/*返回了一个指针，该指针是压入的一个完整的字符串的首字母在stack数组中的位置*/
    c->top += size;/*此时要将stack数组的栈顶索引值top更新*/
    return ret;
}

static void* lept_context_pop(lept_context* c, size_t size) {/*类似的，根据想要弹出的字符串的长度，返回每个字符串在stack数组中对应的首指针*/
    assert(c->top >= size);
    return c->stack + (c->top -= size);/*同时更新top的值*/
}

static void lept_parse_whitespace(lept_context* c) {
    const char *p = c->json;
    while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
        p++;
    c->json = p;
}

static int lept_parse_literal(lept_context* c, lept_value* v, const char* literal, lept_type type) {
    size_t i;
    EXPECT(c, literal[0]);
    for (i = 0; literal[i + 1]; i++)
        if (c->json[i] != literal[i + 1])
            return LEPT_PARSE_INVALID_VALUE;
    c->json += i;
    v->type = type;
    return LEPT_PARSE_OK;
}

static int lept_parse_number(lept_context* c, lept_value* v) {
    const char* p = c->json;
    if (*p == '-') p++;
    if (*p == '0') p++;
    else {
        if (!ISDIGIT1TO9(*p)) return LEPT_PARSE_INVALID_VALUE;
        for (p++; ISDIGIT(*p); p++);
    }
    if (*p == '.') {
        p++;
        if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE;
        for (p++; ISDIGIT(*p); p++);
    }
    if (*p == 'e' || *p == 'E') {
        p++;
        if (*p == '+' || *p == '-') p++;
        if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE;
        for (p++; ISDIGIT(*p); p++);
    }
    errno = 0;
    v->u.n = strtod(c->json, NULL);
    if (errno == ERANGE && (v->u.n == HUGE_VAL || v->u.n == -HUGE_VAL))
        return LEPT_PARSE_NUMBER_TOO_BIG;
    v->type = LEPT_NUMBER;
    c->json = p;
    return LEPT_PARSE_OK;
}

static int lept_parse_string(lept_context* c, lept_value* v) {/*传入c， 解析后的结果存放在v中*/
    size_t head = c->top;
    size_t len;/*head存储原来top的值*/
    const char* p;
    EXPECT(c, '"');/* c->json++ */
    p = c->json;
    for (;;) {
        char ch = *p++;/*先赋值，再自加*/
        switch (ch) {
            case '"':/*代表一个字符串已经读取完毕*/
                len = c->top - head;/*将当前top值减去原top值，得到stack数组中中一个字符串的长度*/
                lept_set_string( v, (const char*)lept_context_pop(c, len), len );/*将字符串填入到v中*/
                c->json = p;
                return LEPT_PARSE_OK;
            case '\\': /* \" \n \t \r 之类的字符会被自动解析出来 而 \\\" \\b 则不行*/
            	switch(*p++){
            	case '\"':PUTC(c, '\"'); break;
            	case '\\':PUTC(c, '\\'); break;
            	case '/':PUTC(c, '/'); break;
            	case 'b':PUTC(c, '\b'); break; 
            	case 'f':PUTC(c, '\f'); break;
            	case 'n':PUTC(c, '\n'); break;
            	case 'r':PUTC(c, '\r'); break;
            	case 't':PUTC(c, '\t'); break;/* 双反斜杠的解析字符就上述的几种，如果其后出现其他的字符，则视为解析错误 */
            	default:
            		c->top = head;
                	return LEPT_PARSE_INVALID_STRING_ESCAPE;/*不正确的转义字符(即ESCAPE)的使用*/
            	}
            	break;
            case '\0':
                c->top = head;
                return LEPT_PARSE_MISS_QUOTATION_MARK;
            default:
            	if ((unsigned char)ch < 0x20) { /*字符的ASCII码中，小于16进制0x20的，是控制字符，无法显示*/
                    c->top = head;
                    return LEPT_PARSE_INVALID_STRING_CHAR;
                }
                PUTC(c, ch);/* ch是读取到的字符，将读取到的字符一个一个压入堆栈中
            		*(char*)lept_context_push(c, sizeof(char)) = (ch) */
        }
    }
}

static int lept_parse_value(lept_context* c, lept_value* v) {
    switch (*c->json) {
        case 't':  return lept_parse_literal(c, v, "true", LEPT_TRUE);
        case 'f':  return lept_parse_literal(c, v, "false", LEPT_FALSE);
        case 'n':  return lept_parse_literal(c, v, "null", LEPT_NULL);
        default:   return lept_parse_number(c, v);
        case '"':  return lept_parse_string(c, v);/* json文本中，字符数据都是以\"开头的,解析时变成" */
        case '\0': return LEPT_PARSE_EXPECT_VALUE;
    }
}

int lept_parse(lept_value* v, const char* json) {
    lept_context c;
    int ret;
    assert(v != NULL);
    c.json = json;
    c.stack = NULL;
    c.size = c.top = 0;
    lept_init(v);/*(v)->type = LEPT_NULL;*/
    lept_parse_whitespace(&c);
    if ((ret = lept_parse_value(&c, v)) == LEPT_PARSE_OK) {
        lept_parse_whitespace(&c);
        if (*c.json != '\0') {
            v->type = LEPT_NULL;
            ret = LEPT_PARSE_ROOT_NOT_SINGULAR;
        }
    }
    assert(c.top == 0);/*确保所有数据都被弹出*/
    free(c.stack);
    return ret;
}

void lept_free(lept_value* v) {
    assert(v != NULL);
    if (v->type == LEPT_STRING)
        free(v->u.s.s);
    v->type = LEPT_NULL;
}

lept_type lept_get_type(const lept_value* v) {
    assert(v != NULL);
    return v->type;
}

int lept_get_boolean(const lept_value* v) {
    assert( v!=NULL && ( v->type==LEPT_TRUE||v->type==LEPT_FALSE ) );
    switch(v->type){
    	case LEPT_TRUE : return 1;
    	case LEPT_FALSE : return 0; 
    }
}

void lept_set_boolean(lept_value* v, int b) {
    lept_free(v);
    switch(b){
    	case 0: v->type=LEPT_FALSE;
    			break;/*此处的break语句是必须的*/
    	default: v->type=LEPT_TRUE;
    }
}

double lept_get_number(const lept_value* v) {
    assert(v != NULL && v->type == LEPT_NUMBER);
    return v->u.n;
}

void lept_set_number(lept_value* v, double n) {
    lept_free(v);
    v->type=LEPT_NUMBER;
    v->u.n=n;
}

const char* lept_get_string(const lept_value* v) {
    assert(v != NULL && v->type == LEPT_STRING);
    return v->u.s.s;
}

size_t lept_get_string_length(const lept_value* v) {
    assert(v != NULL && v->type == LEPT_STRING);
    return v->u.s.len;
}

void lept_set_string(lept_value* v, const char* s, size_t len) {/*给lept_value赋值，
								直接将字符数组的首指针赋值给lept_value * v 中的成员，接着释放堆栈的内存*/
    assert(v != NULL && (s != NULL || len == 0));
    lept_free(v);/*因为不同string的长度不同，所以每次都要先free(),在重新malloc()内存*/
    v->u.s.s = (char*)malloc(len + 1);
    memcpy(v->u.s.s, s, len);/*直接将字符串的首指针复制过来*/
    v->u.s.s[len] = '\0';
    v->u.s.len = len;
    v->type = LEPT_STRING;
}
